/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.sgf.dt.core.service;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.GspProject;
import com.inspur.edp.lcm.metadata.api.service.NoCodeService;
import com.inspur.edp.sgf.api.common.ResourceType;
import com.inspur.edp.sgf.api.common.SummaryInfo;
import com.inspur.edp.sgf.api.entity.ServiceOperation;
import com.inspur.edp.sgf.api.entity.SgMetadata;
import com.inspur.edp.sgf.api.service.EapiMetadataDtService;
import com.inspur.edp.sgf.api.service.EapiRuntimeDeployment;
import com.inspur.edp.sgf.api.utils.ObjectMapperUtil;
import com.inspur.edp.sgf.dt.core.common.EApiDefinitionVO;
import com.inspur.edp.sgf.dt.core.manager.EapiProviderManager;
import com.inspur.edp.sgf.dt.core.utils.MetadataProjectUtils;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.rpc.api.service.RpcClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 功能描述: @ClassName: EapiMetadataDtServiceImpl @Author: Fynn Qi @Date: 2020/12/23 9:55 @Version:
 * V1.0
 */
public class EapiMetadataDtServiceImpl implements EapiMetadataDtService {

    private Logger logger= LoggerFactory.getLogger(EapiMetadataDtServiceImpl.class);

    private final String EAPI_RESOURCE_TYPE_VO = "VO";

    private final String EAPI_RESOURCE_TYPE_VO_SIMPLE = "VO-Simple";

    public static EapiMetadataDtServiceImpl instance;

    static {
        instance = new EapiMetadataDtServiceImpl();
    }

    public void publishOasDoc(String metadataId) {
        GspMetadata metadata = MetadataProjectUtils.getMetadata(metadataId);
        publishOasDoc(metadata);
    }

    @Override
    public GspMetadata create(GspMetadata metadata, String path, ResourceType resourceType) {
        this.validateMetadata(metadata);
        if (StringUtils.isBlank(path)) {
            throw new RuntimeException("EAPI创建时参数校验不通过：依赖元数据的相对路径不能为空");
        }
        String type = getResourceType(resourceType);
        GspMetadata eapiMetadata = EapiProviderManager.instance.createEapi(metadata, path, type);
        try {
            publishOasDoc(eapiMetadata);
        }
        catch (Exception e){
            logger.error("EAPI注册出错："+e.getMessage(),e);
        }
        return eapiMetadata;
    }

    @Override
    public GspMetadata create(GspMetadata metadata, ResourceType resourceType) {
        this.validateMetadata(metadata);
        String type = getResourceType(resourceType);
        GspMetadata eapiMetadata = EapiProviderManager.instance.createEapi(metadata, type);
        //TODO 服务发布后续补充
        return eapiMetadata;
    }

    @Override
    public GspMetadata update(String metadataId, GspMetadata metadata, ResourceType resourceType) {
        this.validateMetadata(metadata);
        String type = getResourceType(resourceType);
        GspMetadata eapiMetadata = EapiProviderManager.instance.updateEapi(metadataId, metadata, type);
        //TODO 服务发布后续补充
        return eapiMetadata;
    }

    @Override
    public void publish(String metadataId) {
        //将设计时的EApi元数据发布到运行时库
        NoCodeService service = SpringBeanUtils.getBean(NoCodeService.class);
        service.publishMetadata(metadataId);
        // 发布REST服务
        EapiRuntimeDeployment deployment = SpringBeanUtils.getBean(EapiRuntimeDeployment.class);
        deployment.deploy(metadataId);
    }

    private void publishOasDoc(GspMetadata eapiMetadata) {
        EApiDefinitionVO vo = getEapiDefinitionVo(eapiMetadata);
        LinkedHashMap<String, Object> map = new LinkedHashMap<>();
        map.put("content", ObjectMapperUtil.serialize(vo));
        SpringBeanUtils.getBean(RpcClient.class).invoke(void.class, "com.inspur.edp.sgf.eapi.doc.api.DevEapiPublishService.getPublishServiceInfo", "sg", map, new HashMap<>());
    }

    private EApiDefinitionVO getEapiDefinitionVo(GspMetadata metadata) {
        EApiDefinitionVO vo = new EApiDefinitionVO();
        vo.setId(metadata.getHeader().getId());
        vo.setServiceCode(metadata.getHeader().getCode());
        vo.setServiceName(metadata.getHeader().getName());
        vo.setServiceUsage("internal");
        vo.setSourceType("Metadata");
        vo.setSourceId(metadata.getHeader().getId());
        vo.setBasePath(getBasePath(metadata));
        GspProject projectInfo = MetadataProjectUtils.getProjectInfo(metadata);
        vo.setServiceUnitCode(projectInfo.getServiceUnitCode());
        vo.setBizObjectId(metadata.getHeader().getBizobjectID());
        vo.setVersion(String.format("v%s", ((SgMetadata) metadata.getContent()).getVersion()));
        return vo;
    }

    private String getBasePath(GspMetadata metadata) {
        SgMetadata sgMetadata = (SgMetadata) metadata.getContent();
        return sgMetadata.getRouter();
    }

    public List<ServiceOperation> getSummaryOperations(String resourceType, String resourceId) {
        List<ServiceOperation> operations = new ArrayList<>();
        List<SummaryInfo> summaryInfos =
                EapiProviderManager.instance.getSummaryOperations(resourceType, resourceId);
        if (summaryInfos != null) {
            for (SummaryInfo summaryInfo : summaryInfos) {
                ServiceOperation operation = new ServiceOperation();
                operation.setId(summaryInfo.getId());
                operation.setCode(summaryInfo.getCode());
                operation.setName(summaryInfo.getName());
                operations.add(operation);
            }
        }
        return operations;
    }

    public List<ServiceOperation> getSelectOperations(
            String resourceType, String resourceId, List<String> operationIds) {
        return EapiProviderManager.instance.getOperations(resourceType, resourceId, operationIds);
    }

    private void validateMetadata(GspMetadata metadata) {
        if (metadata == null) {
            throw new RuntimeException("参数校验不通过：元数据不能为空");
        }
        if (metadata.getHeader() == null) {
            throw new RuntimeException("参数校验不通过：元数据的Header字段不能为空");
        }
        if (StringUtils.isBlank(metadata.getHeader().getType())) {
            throw new RuntimeException("参数校验不通过：元数据类型字段不能为空");
        }
        if (StringUtils.isBlank(metadata.getHeader().getId())) {
            throw new RuntimeException("参数校验不通过：元数据ID字段不能为空");
        }
    }

    /**
     * 获取资源类型
     *
     * @param resourceType 资源类型
     * @return 资源类型解析结果
     */
    private String getResourceType(ResourceType resourceType) {
        switch (resourceType) {
            case VO_ADVANCE:
                return EAPI_RESOURCE_TYPE_VO;
            case VO_SIMPLE:
                return EAPI_RESOURCE_TYPE_VO_SIMPLE;
            default:
                throw new RuntimeException("不支持的资源类型:" + resourceType);
        }
    }
}
